package com.iacrqq.sedaf.demo.sHttpServer.event.handler;

import java.io.IOException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.ConnectionReuseStrategy;
import org.apache.http.HttpException;
import org.apache.http.HttpResponse;
import org.apache.http.HttpResponseFactory;
import org.apache.http.HttpServerConnection;
import org.apache.http.HttpStatus;
import org.apache.http.HttpVersion;
import org.apache.http.impl.DefaultConnectionReuseStrategy;
import org.apache.http.impl.DefaultHttpResponseFactory;
import org.apache.http.params.DefaultedHttpParams;
import org.apache.http.protocol.HttpContext;

import com.iacrqq.sedaf.config.Configuration;
import com.iacrqq.sedaf.demo.sHttpServer.event.HttpEvent;
import com.iacrqq.sedaf.demo.sHttpServer.event.HttpEventStateEnum;
import com.iacrqq.sedaf.event.Event;
import com.iacrqq.sedaf.event.EventDispatcher;
import com.iacrqq.sedaf.event.exception.EventHandlerException;

public class ResponseEventHandler extends AbstractEventHandler
{
	private static final Log logger = LogFactory.getLog(ResponseEventHandler.class);

	private volatile HttpResponseFactory responseFactory = null;
	private volatile ConnectionReuseStrategy connStrategy = null;

	@Override
	public void init(Configuration config) throws Exception
	{
		this.responseFactory = new DefaultHttpResponseFactory();
		this.connStrategy = new DefaultConnectionReuseStrategy();
		System.out.println("ResponseEventHandler initialized.");
	}

	@Override
	public void destroy() throws Exception
	{
		System.out.println("ResponseEventHandler destroied.");
	}

	@Override
	public Event handleEvent(Event event, EventDispatcher eventDispatcher) throws EventHandlerException
	{
		HttpResponse response = null;
		HttpEvent httpEvent = (HttpEvent) event;

		if (httpEvent.getHttpException() != null)
		{
			response = this.responseFactory.newHttpResponse(HttpVersion.HTTP_1_0, HttpStatus.SC_INTERNAL_SERVER_ERROR,
					httpEvent.getHttpContext());
			response.setParams(new DefaultedHttpParams(response.getParams(), this.params));
			_handle_exception_(httpEvent.getHttpException(), response);
		}

		try
		{
			response = httpEvent.getHttpResponse();
			_response_(httpEvent.getHttpContext(), httpEvent.getHttpServerConnection(), response);

			/*if (!this.connStrategy.keepAlive(response, httpEvent.getHttpContext()))
			{
				httpEvent.getHttpServerConnection().close();
			}
			else
			{
				// Keep alive, dispatch to parse stage
				httpEvent.setState(HttpEventStateEnum.HTTP_EVENT_STATE_ACCEPTED.value());
				eventDispatcher.dispatch(httpEvent);
			}*/
			
			httpEvent.getHttpServerConnection().close();
			return null;
		}
		catch (IOException e)
		{
			logger.error(e);
			throw new EventHandlerException(e);
		}
		catch (HttpException e)
		{
			logger.error(e);
			throw new EventHandlerException(e);
		}
		finally
		{
			if(!httpEvent.getHttpServerConnection().isOpen())
			{
				try
				{
					httpEvent.getHttpServerConnection().shutdown();
				}
				catch (IOException e)
				{
					logger.error(e);
					throw new EventHandlerException(e);
				}
			}
		}
	}

	@Override
	public Event[] handleEvents(Event[] events, EventDispatcher eventDispatcher) throws EventHandlerException
	{
		// System.out.println(new
		// StringBuilder("ResponseEventHandler handle ").append(events.length).append(" events:").append(events).toString());

		return events;
	}

	private void _response_(HttpContext context, HttpServerConnection httpServerConnection, HttpResponse response)
			throws HttpException, IOException
	{
		httpServerConnection.sendResponseHeader(response);
		httpServerConnection.sendResponseEntity(response);
		httpServerConnection.flush();
	}
}
